fix(ui): extract theme-flash inline script to /theme-flash.js for strict CSP#104
Merged
fix(ui): extract theme-flash inline script to /theme-flash.js for strict CSP#104
Conversation
…ict CSP The strict CSP shipped from internal/api/security_headers.go uses script-src 'self' 'wasm-unsafe-eval' — no 'unsafe-inline'. The theme-flash FOUC guard in index.html was an inline <script>, so every page load logged a CSP violation: Refused to execute inline script because it violates the following Content Security Policy directive: script-src 'self' 'wasm-unsafe-eval' The script never ran, which meant a brief flash-of-wrong-theme on first paint in dark mode (and vice-versa). Move the script verbatim into ui/public/theme-flash.js (Vite copies public/ to /dist root at build time) and reference it from index.html via <script src="/theme-flash.js">. CSP 'self' allows it without an inline-script exception. The script body is unchanged so behaviour is identical when it runs. Trade-off: one extra HTTP/2 request before paint. The file is 1.2 KiB so this is well below the perceptible-jank threshold and worth it for keeping the strict CSP intact.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The strict CSP shipped from
internal/api/security_headers.gouses:— no
'unsafe-inline'. The theme-flash FOUC guard inui/index.htmlwas an inline<script>block, so every page load logged a CSP violation:The script never ran, which meant a brief flash-of-wrong-theme on first paint when the user's persisted choice differed from the OS preference.
Fix
Move the script body verbatim into
ui/public/theme-flash.js(Vite copiespublic/to/distroot at build time) and reference it fromindex.htmlvia:CSP
'self'allows it without an'unsafe-inline'exception. The script body is unchanged, so behavior is identical when it runs.The
ui/dist/index.htmlplaceholder (committed for//go:embed ui/dist) is updated to match the new structure.Trade-off
One extra HTTP/2 request before paint for
/theme-flash.js(1.2 KiB). Well below the perceptible-jank threshold and worth keeping the strict CSP intact. Could be eliminated with a CSPscript-srcSHA-256 hash, but that introduces hash-sync coupling between the Go server and the JS file — not worth it for a 1.2 KiB script that rarely changes.Test plan
npm --prefix ui run buildproducesdist/theme-flash.js(1.2 KiB)dist/index.htmlno longer contains the inline<script>blockdist/index.htmlcontains<script src=\"/theme-flash.js\">go build -tags sqlite_fts5cleandocsiq serve --port 37794returns HTTP 200 on/AND/theme-flash.js(200, 1227 bytes)/unchangedCompatibility
Drop-in. Behavior of the script is identical; only the delivery mechanism changed.
🤖 Generated with Claude Code